/*
 * Com_Interface.h
 * Last edited: 27.08.2014
 * Author: David Noack
 */

#ifndef COM_INTERFACE_H_
#define COM_INTERFACE_H_

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <pthread.h>
#include <ctime>
#include "signal.h"
#include "MyThreadClass.h"
#include "Prngd.h"
#include "IOUnit.h"

/** Size of the receive buffer for incomming commands*/
#define BUFFER_SIZE 256

/** 
\class Com_Interface
\brief Interface class for all server-classes like Tcp_Server , Udp_Server etc. .

Com_Interfaces provides all the variables and object instances needed for a Prngd-Server.
*/
class Com_Interface{

	public:

		/**Contructor with var initilization*/
		Com_Interface()
		{
			prngd = 0;
			sig = 0;
			worker_busy = false;
			param_count = 0;
			active = false;
			flog = false;
			cmdlog = true;
			params = 0;
			listen_thread_active = false;
			work_thread_active = false;
			lfname = NULL;
			iounit = new IOUnit();
			logTemp = new std::string();
		};

		/**Desctuctor*/
		virtual ~Com_Interface()
		{
			delete iounit;
			delete logTemp;
		};

		/** A Method for polling a server-object.
		\return True if the server is still running, false if it is shutdown.
		*/
		bool isActive(){return this->active;}


	protected:
		/** Instance of the Prngd, which can use BBS or....*/
		Prngd* prngd;

		/** Instance of IOUnit for logging in files*/
		IOUnit* iounit;

		/**Struct for setting the thread attributes*/
		pthread_attr_t attr_obj;
		/**Variable for setting the signalmask*/
		sigset_t sigmask;
		/**A variable for a received signal*/
		int sig;
		/** Struct for setting the signal handler of a signal*/
		struct sigaction action;

		/** Status var of the listen_thread*/
		bool listen_thread_active;
		/** Status var ot the work_thread*/
		bool work_thread_active;

		/**Receive buffer for incomming commands from the client*/
		char work_buffer[BUFFER_SIZE];
		/**Signals if the worker thread is busy with prngd computations*/
		bool worker_busy;
		/**Like argc it gives the number of command parameter received*/
		int param_count;
		/**All the received (from client) command parameters*/
		char** params;
		/**A flag to signal the polling prngd_server that this interface is active or not*/
		bool active;
		/**Name of the logfile, has to be set within a subclass like Tcp_server*/
		char* lfname;
		/**Flag for file logging*/
		bool flog;
		/**Flag for cmd logging*/
		bool cmdlog;
		/**Temp varibale to concatenate some strings*/
		std::string* logTemp;

		/**Thread that will have a Loop with a blocking receive-function like recv or msgrcv*/
		virtual void thread_listen(pthread_t parent_th) = 0;

		/**Thread that will wait for a signal from thread_listen. Prngd will operate within this thread too.*/
		virtual void thread_work() = 0;

		/**A dummy signal handler, so that the default handler will not be called*/
		static void dummy_handler(int){};

		/** Configures the Signal SIGUSR1, SIGUSR2, SIGPOLL.
		The signals will be enabled and bound to the dummy_handler function.
		*/
		void configSignals()
		{
			sigfillset(&sigmask);
			pthread_sigmask(SIG_UNBLOCK, &sigmask, (sigset_t*)0);

			action.sa_flags = 0;
			action.sa_handler = dummy_handler;
			sigaction(SIGUSR1, &action, (struct sigaction*)0);
			sigaction(SIGUSR2, &action, (struct sigaction*)0);
			sigaction(SIGPOLL, &action, (struct sigaction*)0);
		}

		/**
		Reads the parameters from the work_buffer and store them into the two-dimensional array params (like argv).
		\return The number of parameters (like argc).
		*/
		int getParams()
		{
			char* temp = NULL;
			char* temp2 = NULL;

			temp = strchr(work_buffer,' ');
			while(temp != NULL )
			{
				if(*(temp+1) != ' ' && *(temp+1) != '\0')
					param_count++;
				temp  = strchr(temp+1, ' ');

			}
			param_count+=2; //one for the program name + one for the first part of the string

			params = new char*[param_count];

			temp2 = strtok(work_buffer, " ");
			for(int i = 1; temp2 != NULL; i++)
			{
				params[i] = new char[strlen(temp2)+1];
				strncpy(params[i], temp2, strlen(temp2)+1);
				temp2 = strtok(NULL, " ");
			}

			return param_count;
		}


		/**
		Deletes the allocated memory for the two-dimensional array params.
		*/
		void deleteParams()
		{
			for(int i = 1; i < param_count ; i++)
			{
				delete params[i];
			}
			if(params != NULL)
				delete params;
		}

		/**Helps us with the logging in files and command line
		 \param */
		void log(char* msg)
		{
			time_t uTime;
			std::string* temp = new std::string();

			time(&uTime);

			temp->append("\n");
			temp->append(ctime(&uTime));
			temp->erase(temp->end()-1,temp->end());
			temp->append(msg);

			if(flog)
			{
				iounit->writeToFile(lfname, (char*)temp->c_str(), temp->length(), false);
			}
			if(cmdlog)
			{
				std::cout << temp->c_str();
			}

			temp->clear();
			delete temp;
			logTemp->clear();
		}

};



#endif /* COM_INTERFACE_H_ */
